"""Matrix Math
.. helpdoc::
Apply matrix math operations across a matrix of data, this is quite useful for operations that apply some transformation across an image."""

"""
<widgetXML>    
    <name>Matrix Math</name>
    <icon>default.png</icon>
    <tags> 
        <tag>Matplotlib Plotting</tag> 
    </tags>
    <summary>Read an image into the schema.</summary>
    <author>
        <authorname>Kyle R. Covington</authorname>
        <authorcontact>kyle@red-r.org</authorcontact>
    </author>
</widgetXML>
"""
from OWRpy import * 
import redRGUI, signals 
import numpy, scipy, pylab

import redRi18n
_ = redRi18n.get_(package = 'base')
class matrixMath(OWRpy):
    def __init__(self, **kwargs):
        OWRpy.__init__(self, **kwargs)
        self.image1 = None
        self.image2 = None
        
        """.. rrsignals::"""
        self.inputs.addInput('id1', _('Image 1'), signals.base.NumpyArray, self.processImage1)
        
        """.. rrsignals::"""
        self.inputs.addInput('id2', _('Image 2 (optional)'), signals.base.NumpyArray, self.processImage2)
        
        """.. rrsignals::"""
        self.outputs.addOutput('id0', _('Image'), signals.base.NumpyArray)
        
        
        box = redRGUI.base.widgetBox(self.controlArea, orientation = 'horizontal')
        
        self.GUI_imagePresentLabel = redRGUI.base.widgetLabel(box, label = "Image Missing")
        self.GUI_operation = redRGUI.base.comboBox(box, label = "Operation", items = ['>', '<', 'multiply', 'subtract', 'add', 'divide'], toolTip = "Select the operation that will be applied to the matrix")
        self.GUI_constant = redRGUI.base.lineEdit(box, label = "Constant", toolTip = "Set a constant to perform the operation with")
        self.GUI_useImage2 = redRGUI.base.TFCheckBox(box, label = "Use Image 2")
        self.GUI_showImage = redRGUI.base.TFCheckBox(box, label = "Show Image", setChecked = False)
        self.GUI_plot = redRGUI.RedRMatplotlib.mplPlot(self.controlArea)
        
        self.commit = redRGUI.base.commitButton(self.bottomAreaRight, label = _("Commit"), processOnInput=True, callback = self.commitFunction)
    def processImage1(self, data):
        if data:
            self.image1 = data.getData()
            self.GUI_imagePresentLabel.setText(_("Image Present"))
            if self.commit.processOnInput():
                self.commitFunction()
        else:
            self.image1 = None
            self.GUI_imagePresentLabel.setText(_("Image Missing"))
    def processImage2(self, data):
        if data:
            self.image2 = data.getData()
            if self.commit.processOnInput():
                self.commitFunction()
        else:
            self.image2 = None
    def commitFunction(self):
        if self.image1 == None:
            self.status.setText(_("Image 1 Not Present"))
            return
        try: # there is the possibility that the user will try to apply some operation across a non conformable array, we need to check this so that we don't mess up the entire pipeline.
            if self.GUI_useImage2.checked() == 'TRUE':
                if self.image2 == None:
                    self.status.setText(_("Image 2 Not Present"))
                    return
                newData = self.execFunction(self.image2)
            elif self.GUI_constant.text() != '':
                constant = float(self.GUI_constant.text())
                newData = self.execFunction(constant)
        except Exception as inst:
            self.status.setText("Exception ocurred: %s" % inst)
            return
            
        if self.GUI_showImage.checked() == "TRUE":
            self.GUI_plot.subPlot.clear()
            self.GUI_plot.subPlot.imshow(newData)
            self.GUI_plot.canvas.draw()
        
        nd = signals.base.NumpyArray(self, data = newData)
        self.rSend('id0', nd)
        
    def execFunction(self, o):
        function = self.GUI_operation.currentId()
        if function == '>':
            return self.image1 > o
        elif function == '<':
            return self.image1 < o
        elif function == 'multiply':
            return numpy.multiply(self.image1, o)
        elif function == 'subtract':
            return numpy.subtract(self.image1, o)
        elif function == 'add':
            return numpy.add(self.image1, o)
        elif function == 'divide':
            return numpy.divide(self.image1, o)